package be.one.paq.repository.impl;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;

import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.support.JpaDaoSupport;

import be.one.paq.repository.IGenericRepository;

public abstract class GenericJpaRepository<K, E> extends JpaDaoSupport implements IGenericRepository<K, E> {

	protected Class<E> entityClass; 
	
    @SuppressWarnings("unchecked")
    public GenericJpaRepository() {
    	ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
    	this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[1];
    }
    	 
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#persist(E)
	 */
    public void persist(E entity) {
        getJpaTemplate().persist(entity);
    }
 
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#remove(E)
	 */
    public void remove(E entity) {
        getJpaTemplate().remove(entity);
    }
     
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#merge(E)
	 */
    public E merge(E entity) {
        return getJpaTemplate().merge(entity);
    }
     
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#refresh(E)
	 */
    public void refresh(E entity) {
        getJpaTemplate().refresh(entity);
    }
 
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#findById(K)
	 */
    public E findById(K id) {
        return getJpaTemplate().find(entityClass, id);
    }
     
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#flush(E)
	 */
    public E flush(E entity) {
        getJpaTemplate().flush();
        return entity;
    }
    	     
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#findAll()
	 */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public List<E> findAll() {    	
    	return (List<E>) getJpaTemplate().execute(new JpaCallback() {        	
            public Object doInJpa(EntityManager em) throws PersistenceException {
            	return em.createQuery("SELECT h FROM " + entityClass.getName() + " h").getResultList();
            }             
        });         
    }
    	 
    /* (non-Javadoc)
	 * @see be.one.paq.repository.IGenericRepository#removeAll()
	 */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public Integer removeAll() {
        return (Integer) getJpaTemplate().execute(new JpaCallback() {
            public Object doInJpa(EntityManager em) throws PersistenceException {
            	return em.createQuery("DELETE FROM " + entityClass.getName() + " h").executeUpdate();
            }             
        });
    }	
    
}
